using System;
using System.Collections.Generic;
using System.Text;
using MyMath;

namespace Physics
{
    public struct DiceResult
    {
        public int dice1;
        public int dice2;
    }

    public delegate void DiceEvent(DiceResult result);

    public class DiceSimulation
    {
        Dice[] dices = new Dice[2];

        public Dice[] Dices
        {
            get { return dices; }
        }

        DiceTable diceTable;


        public const float AnimationStep = 0.02f;

        public const float TableWidth = 70;
        public const float TableLength = 70;
        public const float TableDepth = 35;

        readonly MyVector startingPosition = new MyVector(0, -TableDepth/2, TableLength/3);

        public const float DiceSize = 4f;

        float animationTime = 0;
        float timeToProcess = 0;

        public event DiceEvent OnSimulationEnd;

        RigidBodySimulator physicsSimulator;

        public RigidBodySimulator PhysicsSimulator
        {
            get { return physicsSimulator; }
        }

        public DiceSimulation()
        {
            physicsSimulator = new RigidBodySimulator();
            CollisionDetectorWC wcdetector = new CollisionDetectorWC(physicsSimulator);
            physicsSimulator.CollisionDetector = wcdetector;
            physicsSimulator.DoGravity = true;
            physicsSimulator.DoLinearDrag = true;
            physicsSimulator.DoAngularDrag = true;

            dices[0] = new Dice(DiceSize);
            dices[1] = new Dice(DiceSize);

            physicsSimulator.AddObject(dices[0]);
            physicsSimulator.AddObject(dices[1]);

            diceTable = new DiceTable(TableWidth, TableLength, TableDepth);
            wcdetector.AddConstrainingObject(diceTable);
        }

        public void StartSimulation(MyVector direction,float velocity)
        {
            direction.Normalize();
            timeToProcess = 0;
            animationTime = 0;

            dices[0].Position = startingPosition + new MyVector(-2 * DiceSize, 0, 0) - direction * velocity/2;


            dices[1].Position = startingPosition + new MyVector(2 * DiceSize, 0, 0) - direction * velocity/2;


            //dices[0].Velocity = new MyVector(1, 1, -10);
            //dices[1].Velocity = new MyVector(-1, 1, -10);

            //dices[0].Orientation = MyQuaternion.FromEulerAngles(0, (float)Math.PI / 5, (float)Math.PI / 5);
            //dices[1].Orientation = MyQuaternion.FromEulerAngles(0, (float)Math.PI / 3, (float)Math.PI / 2);
            MyVector pos1 = dices[0].Position;
            MyVector pos2 = dices[1].Position;

            dices[0].Orientation = MyQuaternion.FromEulerAngles(pos1.X, pos1.Y, pos1.Z);
            dices[0].Velocity = direction * velocity;
            dices[0].AngularVelocity = 3 * direction + dices[0].Orientation.Axis;
            dices[0].Type = ObjectType.RigidBody;

            dices[1].Orientation = MyQuaternion.FromEulerAngles(pos2.X, pos2.Y, pos2.Z);
            dices[1].Velocity = direction*velocity;
            dices[1].AngularVelocity = 3 * direction + dices[1].Orientation.Axis;
            dices[1].Type = ObjectType.RigidBody;


            physicsSimulator.Paused = false;
        }

        public void UpdateSimulation(float dt)
        {
            if (dt > AnimationStep)
                dt = AnimationStep;
            timeToProcess+=dt;
            animationTime += dt;
            if (timeToProcess > AnimationStep)
            {
                timeToProcess -= AnimationStep;
                physicsSimulator.AdvanceSimulation(AnimationStep);

                bool status = true;
                foreach (IPhysicalObject s in physicsSimulator.Objects)
                {

                    if (s.Velocity.LengthSq < 0.3f && s.Position.Y < -TableDepth + 0.1f + DiceSize / 2)
                    {
                        s.Type = ObjectType.Static;
                        s.Velocity = new MyVector(0, 0, 0);
                        s.AngularVelocity = new MyVector(0, 0, 0);
                    }
                    else
                    {
                        status = false;
                    }
                }
                if (status)
                {
                    physicsSimulator.Paused = true;
                    if (OnSimulationEnd != null)
                    {
                        OnSimulationEnd(Result);
                    }
                }
            }
            if (animationTime > 10)
            {
                physicsSimulator.Paused = true;
                if (OnSimulationEnd != null)
                {
                    OnSimulationEnd(Result);
                }
            }
        }

        public DiceResult Result
        {
            get
            {
                DiceResult res = new DiceResult();
                res.dice1 = dices[0].Side;
                res.dice2 = dices[1].Side;
                return res;
            }
        }

        public DiceResult ComputeResult(MyVector direction,float velocity)
        {
            StartSimulation(direction, velocity);

            while (physicsSimulator.Paused==false)
            {
                UpdateSimulation(AnimationStep);



                //check sim
            }



            return Result; 
        }
    }
}
